const usersModel = require("../model/UsersModel.js");
const bcrypt = require("bcrypt");
const { generateToken, revokeToken } = require("../services/tokenService");

const logService = require("../utils/logService");
const LOG_TYPES = require("../constants/logTypes");
const { getClientType } = require("../utils/utils");

// ES6 Class - 推荐
class UsersController {
  constructor() {
    this.usersModel = new usersModel();
  }
  // 获取用户列表
  async getUsers(req, res) {
  try {
    // 解构查询参数，包括 role_id
    let { page = 1, page_size = 10, user_name, status, role_id } = req.query;

    // 设置默认值
    if (!user_name) user_name = '';
    if (status === '' || status === undefined) status = '';
    if (role_id === '' || role_id === undefined) role_id = '';

    const { rows, total } = await this.usersModel.getUsersPage({
      page: Number(page),
      size: Number(page_size),
      keyword: user_name,
      status: status,
      role_id: role_id

    });

    return res.json({
      code: 0,
      msg: '获取用户列表成功',
      page: Number(page),
      page_size: Number(page_size),
      total,
      data: rows.map(u => ({
        user_id: u.user_id,
        user_name: u.user_name,
        role_id: u.role_id,
        status: u.status,
        phone: u.phone,
        email: u.email,
        created_at: u.created_at,
        updated_at: u.updated_at,
        login: u.login,
        notes: u.notes          
      })),
      authenticated_as: req.userId
        ? `User ID: ${req.userId}, Role ID: ${req.roleId}`
        : '未认证',
    });
  } catch (e) {
    console.error('getUsers error:', e.message);
    return res.status(500).json({
      code: 1,
      msg: '获取用户列表失败，请检查模型层',
    });
  }
}

  // 用户登录 (公开接口)
  async login(req, res) {
    const { user_name, password } = req.body;

    // 1. 基础校验
    if (!user_name || !password) {
      return res.json({ code: 1, msg: "用户名或密码不能为空" });
    }

    // 验证数据类型
    if (typeof user_name !== 'string' || typeof password !== 'string') {
      return res.json({ code: 1, msg: "用户名和密码必须是字符串" });
    }

    // 验证长度
    if (user_name.length > 100) {
      return res.json({ code: 1, msg: "用户名长度不能超过100个字符" });
    }

    if (password.length > 100) {
      return res.json({ code: 1, msg: "密码长度不能超过100个字符" });
    }

    try {
      // 2. 获取用户信息、检查用户是否存在
      const [user] = await this.usersModel.checkUser(user_name);

      if (!user) {
        return res.json({ code: 1, msg: "用户不存在或密码错误" });
      }

      // 3. 验证密码
      const compareResult = await bcrypt.compare(password, user.password);

      if (!compareResult) {
        return res.json({ code: 1, msg: "用户不存在或密码错误" });
      }

      // 4. 检查用户状态（防止登录禁用用户）
      if (user.status !== 1) {
        return res.json({ code: 1, msg: "用户已被禁用，无法登录" });
      }

      // 登录成功，使用 tokenService 生成 Access Token
      // 携带 user_id 和 role_id
      const token = await generateToken(user.user_id, user.role_id);

      let userInfo = {
        user_name: user.user_name,
        user_id: user.user_id,
        role_id: user.role_id,
        status: user.status,
      };

      // 6. 记录登录日志
      console.log("登录类型："+LOG_TYPES.LOGIN)

      // 登录日志的op_desc
      const client_type = getClientType(req);
      const logDesc = logService.formatLog(
          LOG_TYPES.LOGIN,
          {user_id: user.user_id,user_name: user.user_name,client_type});
      // 组装日志数据
      const logData = {
        user_id: user.user_id,   //登录时必须带上user_id，因为登录时没有token，没有user_id
        op_type: LOG_TYPES.LOGIN,//日志类型-必填
        op_desc: logDesc         //日志描述-必填
      };
      logService.addLog(req,logData);

      // 5. 返回数据
      return res.json({
        code: 0,
        msg: "登录成功",
        data: {
          ...userInfo,
          token,
        },
      });
    } catch (error) {
      console.error("Login Error:", error.message);
      // 数据库异常或查询不到数据时都返回通用错误信息
      return res.status(500).json({ code: 1, msg: "服务器内部错误" });
    }
  }

  // 用户退出登录
  async logout(req, res) {
    // 通过 authMiddleware 获取到 req.tokenId
    const tokenId = req.tokenId;

    if (tokenId) {
      try {
        // 使用 revokeToken 实时作废 Redis 中的 Token 状态
        await revokeToken(tokenId);
      } catch (error) {
        console.error(`注销失败，无法撤销令牌 ${tokenId}: ${error.message}`);
      }
    }
    // 记录日志
    const user = req.user; // 获取用户信息
    if ( user.user_id){
      // 登录日志的op_desc
      const logDesc = logService.formatLog(LOG_TYPES.LOGOUT,{user_id: user.user_id,user_name: user.user_name});
      // 组装日志数据
      const logData = {
        op_type: LOG_TYPES.LOGOUT,
        op_desc: logDesc
      };
      logService.addLog(req,logData);
    }

    return res.json({
      code: 0,
      msg: "退出登录成功",
    });
  }
    //   添加用户
  async addUser(req, res) {
    try {
      // 验证输入参数
      const { user_name, password, role_id, phone, email, status, notes } = req.body;

      // 验证必填字段
      if (!user_name) {
        return res.status(400).json({ code: 1, message: "用户名不能为空" });
      }

      if (!phone) {
        return res.status(400).json({ code: 1, message: "电话不能为空" });
      }

      if (!email) {
        return res.status(400).json({ code: 1, message: "邮箱不能为空" });
      }

      // 验证数据类型和长度
      if (typeof user_name !== 'string' || user_name.length > 100) {
        return res.status(400).json({ code: 1, message: "用户名必须是长度不超过100的字符串" });
      }

      // 如果提供了密码，验证密码长度
      if (password !== undefined && password !== null && password !== '') {
        if (typeof password !== 'string' || password.length < 6 || password.length > 100) {
          return res.status(400).json({ code: 1, message: "密码长度必须在6-100个字符之间" });
        }
      }

      if (typeof phone !== 'string' || !/^1[3-9]\d{9}$/.test(phone)) {
        return res.status(400).json({ code: 1, message: "电话号码格式不正确" });
      }

      if (typeof email !== 'string' || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
        return res.status(400).json({ code: 1, message: "邮箱格式不正确" });
      }

      // 验证角色ID
      if (role_id !== undefined) {
        const roleIdNum = Number(role_id);
        if (isNaN(roleIdNum) || roleIdNum < 1 || roleIdNum > 3) {
          return res.status(400).json({ code: 1, message: "角色ID必须是1-3之间的数字" });
        }
      }

      // 验证状态
      if (status !== undefined) {
        const statusNum = Number(status);
        if (isNaN(statusNum) || (statusNum !== -1 && statusNum !== 0 && statusNum !== 1)) {
          return res.status(400).json({ code: 1, message: "状态必须是-1、0或1" });
        }
      }

      if (notes !== undefined && typeof notes !== 'string') {
        return res.status(400).json({ code: 1, message: "备注必须是字符串" });
      }

      // 对密码进行哈希处理，如果没有提供密码则使用默认密码
      const defaultPassword = "123456aA";
      const hashedPassword = await bcrypt.hash(password || defaultPassword, 10);

      // 准备数据
      const userData = {
        user_name,
        password: hashedPassword,
        role_id: role_id || 2,
        phone,
        email,
        status: status !== undefined ? Number(status) : 1,
        notes: notes || ""
      };

      const id = await this.usersModel.insertUser(userData);
      res.json({ code: 0, msg: "添加成功", data: { userid: id } });
    } catch (e) {
      console.error("Add User Error:", e);

      if (e && e.message) {
        if (e.message.includes("用户名已被占用")) {
          return res.status(400).json({ code: 1, msg: "用户名已被占用" });
        }
        if (e.message.includes("手机号已被占用")) {
          return res.status(400).json({ code: 1, msg: "手机号已被占用" });
        }
        if (e.message.includes("邮箱已被占用")) {
          return res.status(400).json({ code: 1, msg: "邮箱已被占用" });
        }
      }

      res.status(500).json({ code: 1, msg: e && e.message ? e.message : "服务器内部错误" });
    }
  }
  // 修改用户
  async updateUser(req, res) {
    try {
      // 验证用户ID参数
      const user_id = req.params.user_id;
      if (!user_id) {
        return res.status(400).json({ code: 1, message: "用户ID不能为空" });
      }

      const userIdNum = Number(user_id);
      if (isNaN(userIdNum) || userIdNum <= 0) {
        return res.status(400).json({ code: 1, message: "用户ID必须是大于0的数字" });
      }

      // 获取要更新的数据
      const { user_name, role_id, phone, email, status, notes } = req.body;

      // 检查是否有要更新的数据
      if (user_name === undefined && role_id === undefined && phone === undefined &&
        email === undefined && status === undefined && notes === undefined) {
        return res.status(400).json({ code: 1, message: "没有提供要更新的数据" });
      }

      // 验证提供的数据
      const updateData = {};

      if (user_name !== undefined) {
        if (typeof user_name !== 'string' || user_name.length > 100) {
          return res.status(400).json({ code: 1, message: "用户名必须是长度不超过100的字符串" });
        }
        updateData.user_name = user_name;
      }

      if (role_id !== undefined) {
        const roleIdNum = Number(role_id);
        if (isNaN(roleIdNum) || roleIdNum < 1 || roleIdNum > 3) {
          return res.status(400).json({ code: 1, message: "角色ID必须是1-3之间的数字" });
        }
        updateData.role_id = roleIdNum;
      }

      if (phone !== undefined) {
        if (typeof phone !== 'string' || !/^1[3-9]\d{9}$/.test(phone)) {
          return res.status(400).json({ code: 1, message: "电话号码格式不正确" });
        }
        updateData.phone = phone;
      }

      if (email !== undefined) {
        if (typeof email !== 'string' || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
          return res.status(400).json({ code: 1, message: "邮箱格式不正确" });
        }
        updateData.email = email;
      }

      if (status !== undefined) {
        const statusNum = Number(status);
        if (isNaN(statusNum) || (statusNum !== -1 && statusNum !== 0 && statusNum !== 1)) {
          return res.status(400).json({ code: 1, message: "状态必须是-1、0或1" });
        }
        updateData.status = statusNum;
      }

      if (notes !== undefined) {
        if (typeof notes !== 'string') {
          return res.status(400).json({ code: 1, message: "备注必须是字符串" });
        }
        updateData.notes = notes;
      }

      const affected = await this.usersModel.updateUser(
        user_id,
        updateData
      );
      res.json({ code: 0, msg: affected ? "修改成功" : "记录不存在" });
    } catch (e) {
      console.error("Update User Error:", e.message);
      res.status(500).json({ code: 1, msg: e.message });
    }
  }
  // 删除用户
  async deleteUser(req, res) {
    try {
      // 验证用户ID参数
      const user_id = req.params.user_id;
      if (!user_id) {
        return res.status(400).json({ code: 1, message: "用户ID不能为空" });
      }

      const userIdNum = Number(user_id);
      if (isNaN(userIdNum) || userIdNum <= 0) {
        return res.status(400).json({ code: 1, message: "用户ID必须是大于0的数字" });
      }

      const affected = await this.usersModel.deleteUser(user_id);
      res.json({ code: 0, msg: affected ? "删除成功" : "记录不存在" });
    } catch (e) {
      console.error("Delete User Error:", e.message);
      res.status(500).json({ code: 1, msg: e.message });
    }
  }
  // 修改密码
  async changePassword(req, res) {
    try {
      // 验证用户ID参数
      const user_id = req.params.user_id;
      if (!user_id) {
        return res.status(400).json({ code: 1, message: "用户ID不能为空" });
      }

      const userIdNum = Number(user_id);
      if (isNaN(userIdNum) || userIdNum <= 0) {
        return res.status(400).json({ code: 1, message: "用户ID必须是大于0的数字" });
      }

      // 获取要更新的数据
      const body = req.body;
      const old_password = body.old_password;
      const new_password = body.new_password;
      
      console.log("新值"+new_password, "旧值"+old_password);
      // 检查是否有要更新的数据
      if (old_password === undefined && new_password === undefined) {
         return res.status(400).json({ code: 1, message: "旧密码和新密码不能为空" });
      } else {
       const isMatch = await this.usersModel.checkOldPassword(user_id,old_password);
       if (!isMatch) {
        return res.status(400).json({ code: 1, message: "旧密码错误" });
       } else {
        const affected = await this.usersModel.updatePassword(user_id,new_password);
        res.json({ code: 0, msg: affected ? "修改成功" : "修改失败" });
       }
      }
    } catch (error) {
      console.error("Change Password Error:", error.message);
      res.status(500).json({ code: 1, msg: error.message });
    }
  }

  //根据用户id重置密码为123456aA
  /*
  * @description 根据用户id重置密码为123456aA
  * @param req 请求对象
  * @param res 响应对象
  * @param user_id 用户id
  * @return
  * */
  async resetPassword(req, res) {
    try {
     const user_id = req.params.user_id;
     if (!user_id) {
      return res.status(400).json({ code: 1, message: "用户ID不能为空" });
     }

     const userIdNum = Number(user_id);
     if (isNaN(userIdNum) || userIdNum <= 0) {
      return res.status(400).json({ code: 1, message: "用户ID必须是大于0的数字" });
     }

     const pwd =await bcrypt.hash("123456aA", 10)
     const affected = await this.usersModel.updatePassword(user_id, pwd);
     res.json({ code: 0, msg: affected ? "密码已重置为:123456aA" : "重置失败" });
    } catch (error) {
      console.error("Reset Password Error:", error.message);
      res.status(500).json({ code: 1, msg: error.message });
    }
  }
}

// 导出UsersController类
module.exports = UsersController;